iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0

昨天在整理 AI Engineering 的時候,我比較在意的是一件事:當 AI 的答案出錯,我到底能不能知道問題發生在哪一層。

到了今天,我想往前再走一步,因為就算現在 Prompt 已經調到看起來很穩、Demo 每次測也都能正常回答,其實離「真的可以放進產品裡給別人用」還有一段距離。

這個差距以前其實沒有那麼明顯,我自己做小專案的時候也很容易有一種錯覺,只要 API 接得起來、Prompt 寫得夠好、畫面上能吐出答案,好像功能就已經完成了。但真的把流程拆開之後才發現,Demo 成功通常只代表一件事:在我準備好的輸入下,模型剛好給出了我想要的結果。

真正上線之後,使用者不會照著我測試時的方式輸入資料。

有人會少打一個欄位、有人一次貼幾千字、有人問完全不在預期範圍裡的問題,也可能 API 突然 timeout、模型回傳格式跑掉,甚至同一個問題隔幾分鐘再問一次,答案就長得不太一樣。這些事情單看 Prompt 幾乎都解決不了。

所以今天我想實際拆一次,一個「可以 Demo 的 AI 功能」到底還缺了什麼,才有辦法慢慢變成一個真的能放進系統裡的功能。

我先做了一個最簡單的 AI Demo

假設今天要做一個客服分類功能,輸入一段使用者訊息,讓模型判斷它屬於:

  • 帳號問題
  • 付款問題
  • 技術問題
  • 其他

最簡單的寫法其實很直覺。

prompt = f"""
請判斷下面這則客服訊息屬於哪一類:

帳號問題
付款問題
技術問題
其他

訊息:
{user_message}

只回答分類名稱。
"""

接著把 Prompt 丟給模型,再把模型回傳的文字顯示出來。

如果測試資料是:

我的信用卡已經扣款,但系統還是顯示尚未付款

模型回:

付款問題

看起來完全沒問題。

再測幾筆也都正常,這時候如果只是做課堂 Demo,其實已經可以收工了,但如果這段結果下一步要直接進資料庫、觸發客服分流,事情就開始不一樣。

因為系統真正需要的不是「模型看起來回答對」,而是我能不能確定接下來的程式知道該怎麼處理這個答案。

第一個問題:模型回什麼,程式真的知道嗎?

我原本叫模型「只回答分類名稱」,但這其實只是一個要求,不是一個保證。

今天模型可能回:

付款問題

明天也可能變成:

這看起來屬於付款問題。

甚至是:

分類:付款問題
原因:使用者已經被扣款,但付款狀態沒有更新。

人看得懂,程式不一定看得懂。

如果後面寫的是:

if result == "付款問題":
    assign_to_payment_team()

那第二種、第三種輸出全部都會失敗。

所以第一個很明顯的差異是,Production 不能只依賴「Prompt 叫模型乖乖輸出」,還需要限制輸出格式。

例如把答案改成固定 JSON:

{
  "category": "payment"
}

程式收到結果之後,再檢查 category 是不是只出現在允許的四個值裡。

allowed_categories = {
    "account",
    "payment",
    "technical",
    "other"
}

if result["category"] not in allowed_categories:
    # 不直接往下執行
    handle_invalid_output()

做到這一步,AI 才比較像系統裡的一個 component,而不是一個會自由回答問題的聊天室。

第二個問題:使用者不會只給你漂亮的測試資料

Demo 時我會自己準備輸入,例如:

我的信用卡已經扣款,但系統顯示付款失敗

可是上線之後可能收到:

不能用

或者:

???

甚至直接有人貼了一整篇文章進來。

如果每個輸入都直接送給 LLM,我等於把所有判斷責任全部丟給模型,但有些東西根本不需要進到模型。

所以在 Prompt 前面其實還要有一層 Input Validation。

使用者輸入
    ↓
輸入檢查
    ↓
Prompt
    ↓
LLM

例如最基本可以先檢查:

if not user_message.strip():
    return "請輸入問題"

if len(user_message) > 2000:
    return "輸入內容過長"

再往後甚至可以檢查語言、必要欄位、資料格式,或先判斷這個輸入到底是不是目前功能能處理的內容。

以前我會覺得這些跟 AI 沒什麼關係,但開始把 AI 當成產品的一部分之後,反而會發現這些普通的軟體工程工作非常重要。

因為模型本身已經是不確定的元件,如果模型前後又全部沒有規則,整個系統最後會變得很難控制。

第三個問題:模型失敗的時候要怎麼辦?

Demo 很少特別測這件事。

API 正常、網路正常、模型正常,一路跑到底,看起來當然沒有問題。

但 Production 一定會遇到:

Timeout
Rate Limit
API Error
Invalid JSON
模型拒答
模型輸出不符合 Schema

這時候如果程式只有:

response = call_llm(prompt)
return response

任何一個環節出錯,整個功能就一起掛掉。

所以這裡開始需要一些原本在 Demo 幾乎不會注意的東西,例如 timeout、retry 和 fallback。

try:
    response = call_llm(
        prompt,
        timeout=10
    )
except TimeoutError:
    return fallback_response()

Retry 也不是無限重試,而是可能只允許一兩次,不然一個使用者請求就會在背景一直燒 API 費用。

for attempt in range(2):
    try:
        response = call_llm(prompt)
        break
    except Exception:
        if attempt == 1:
            return fallback_response()

這些程式本身其實沒有很難,但我覺得觀念上的差別很大。

Demo 的思考方式通常是:

模型成功的時候,我可以做到什麼?

Production 要開始問的是:

模型失敗的時候,我的系統會發生什麼?

第四個問題:答案錯了,我怎麼知道?

這也是我今天整理時覺得差距最大的地方。

假設客服分類每天處理 10,000 筆資料,其中 300 筆被分類錯誤,如果系統只是單純把 LLM 結果寫進資料庫,其實我可能根本不知道那 300 筆存在。

程式沒有 crash,API 也全部回 200,看起來系統運作得非常健康,但 AI 的品質其實正在下降。

所以一般 Backend 常看的東西可能是:

API 有沒有掛
Latency 多高
Error Rate 多少
CPU / Memory 是否正常

AI 系統還需要另外知道:

模型現在回答得好不好?
輸出格式錯誤多少次?
Fallback 發生多少次?
不同類型問題的準確率如何?
Prompt 改版之後有沒有退步?

這裡就開始碰到 Evaluation 和 Observability。

至少我需要把每次請求的一些資訊留下來:

{
  "request_id": "abc123",
  "prompt_version": "v2",
  "model": "gpt-x",
  "latency_ms": 820,
  "category": "payment",
  "fallback": false
}

如果之後真的發生問題,我才有東西可以回頭查。

不然只知道「AI 最近好像怪怪的」,其實根本沒有辦法 debug。

Prompt 也開始需要版本管理

還有一個以前很容易忽略的問題。

假設今天覺得分類效果不好,我把:

請判斷下面的客服問題屬於哪一類

改成:

你是一位客服分類專員,請根據使用者主要問題選擇最符合的分類

測了幾筆,好像比較準,就直接把 Prompt 改掉。

但一週後發現「技術問題」突然常被分到「其他」,這時候第一個問題就是:

到底是哪一次修改造成的?

如果 Prompt 只是散落在程式碼裡的一段字串,我很難追。

所以 Prompt 本身也需要版本,例如:

PROMPT_VERSION = "customer_classification_v3"

每次 request 同時記錄使用的是哪個版本。

這樣之後才能比較:

v1 accuracy:84%
v2 accuracy:89%
v3 accuracy:82%

看到這個結果之後,至少我知道 v3 可能不是升級,而是 regression。

這件事其實跟一般軟體的版本管理很像,只是以前我們主要在管 code,現在 Prompt 和模型設定本身也變成系統行為的一部分。

所以一個 AI 功能真正的流程開始變長了

如果把今天整理的東西全部放回來,原本的 Demo 可能只有:

User
 ↓
Prompt
 ↓
LLM
 ↓
Answer

但真的準備上線時,慢慢會變成:

User
 ↓
Input Validation
 ↓
Prompt Template
 ↓
LLM
 ↓
Structured Output
 ↓
Schema Validation
 ↓
Business Logic
 ↓
Response

旁邊還另外會有:

Logging
Evaluation
Retry
Fallback
Monitoring
Prompt Version

這時候 Prompt 還是很重要,但它只是整條流程中的一部分。

而我現在理解的 AI Engineering,比較接近是在處理這整條路,而不只是把中間那個 Prompt 寫得更漂亮。

今天最想留下來的是 Demo 和 Production 的差別

我以前做 AI 功能時,很容易把「模型有回答」當成「功能完成」。

但今天把流程拆開後,我覺得比較合理的判斷方式應該是:

Demo:
正常輸入進來時,AI 能不能完成任務?

Production:
輸入亂掉、模型亂掉、API 掛掉、輸出格式改變時,
整個系統還能不能正常處理?

真正麻煩的通常不是那一次成功的回答,而是剩下那些沒有按照預期發生的情況。

所以今天沒有特別去追更複雜的 Agent 或 RAG,而是先把一個最普通的 LLM 功能往 Production 推一步,補上輸入檢查、Structured Output、Schema Validation、Retry、Fallback 和 Logging。

這幾個東西單獨看都很普通,但接起來之後,AI 才開始從「可以玩的 Demo」變成一個真的能被系統使用的元件。

明天我想繼續往這個問題走,實際處理另一個更麻煩的地方:

AI 的答案沒有報錯,但答案其實是錯的,我要怎麼自動發現?


上一篇
Day 1|你的 AI Demo 真的能上線嗎?從「會動」開始談 AI Engineering
下一篇
Day 3 :AI 回答看起來沒問題,就真的沒問題嗎?我開始替輸出加上評分標準
系列文
你的 AI Demo 為什麼不能上線?從 Prompt 到 Production 的 AI Engineering3
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言